package de.bazinga.rotw.base.attacker;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;

import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Controller;
import com.jme.scene.Node;
import com.jmex.game.state.GameStateManager;
import com.jmex.model.animation.JointController;

import de.bazinga.rotw.game.Game;
import de.bazinga.rotw.game.RotwGameState;
import de.bazinga.rotw.gameModes.DefendYourBase;
import de.bazinga.rotw.model.ModelCache;
import de.bazinga.rotw.network.BasicSyncManager;
import de.bazinga.rotw.network.Server;
import de.bazinga.rotw.person.Person;
import de.bazinga.rotw.sound.Sound;
import de.bazinga.rotw.statistics.OnlineStatistics;

public class BaseAttacker extends Node {
	private static final long serialVersionUID = 1L;

	/**
	 * Each Attacker has his own ID, so we can
	 * identify him thru the network
	 */
	private int attackerId = 0;
	
	
	/**
	 * 0 => Zombie
	 * 1 = >Dwarf
	 */
	private int modelIndex = 0;
	
	
	/**
	 * Health
	 */
	private int health = 100;
	
	/**
	 * The maximum health (will increase by time
	 */
	public static int MAXHEALTH = 100;
	
	/**
	 * AnimationController
	 */
	private JointController controller = null;
	
	/**
	 * BaseAttackerController moves the Attacker to the base
	 */
	private BaseAttackerController baseAttackerController = null;
	
	
	/**
	 * The time when he died
	 */
	private long timeDied = 0;
	
	
	public BaseAttacker(int id) {
		modelIndex =  new Random().nextInt(2);
		setAttackerId(id);
		
		setLocalTranslation(0, -999, 0);
		
		loadModel();
		
		if(modelIndex == 0) {
			controller.setTimes(2, 20);
		}else{
			controller.setTimes(16, 26);
		}
		controller.setActive(true);
		
		baseAttackerController = new BaseAttackerController(this);
		this.addController(baseAttackerController);
		baseAttackerController.setActive(true);
		
		
		setCullHint(CullHint.Always);
		setIsCollidable(false);
	}
	
	public BaseAttacker() {
		this(new Random().nextInt(999999999));
	}
	
	protected void loadModel() {		
		// Load Model
		URL zombieUrl = null;
		try {
			if(modelIndex == 0) zombieUrl = new File("player/zombie/").toURI().toURL();
			else zombieUrl = new File("player/dwarf/").toURI().toURL();
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		}
		String modelFile = "";
		if(modelIndex == 0) modelFile = "/player/zombie/zombie02.ms3d";
        else modelFile = "/player/dwarf/dwarf1.ms3d";
        
		
		Node zombie = ModelCache.getInstance().loadModel(zombieUrl, zombieUrl, modelFile);
		
        if(modelIndex == 0) zombie.setLocalScale(0.14f);
        else zombie.setLocalScale(0.05f);
        
        Quaternion rot180 = new Quaternion();
        rot180.fromAngleAxis(135, Vector3f.UNIT_Y);
        if(modelIndex == 1) zombie.setLocalRotation(rot180);
        
        this.attachChild(zombie);
        
        
        
        
        controller = (JointController)zombie.getController(0);
        controller.setRepeatType(Controller.RT_CYCLE);
        if(modelIndex == 0) controller.setSpeed(1f);
        else controller.setSpeed(0.5f);
        controller.setActive(false);
	}
	
	
	public void reset() {
		RotwGameState gameState = (RotwGameState)GameStateManager.getInstance().getChild("gameState");
		DefendYourBase gameMode = (DefendYourBase)gameState.getGameMode();
		
		reset(gameMode.getRandomAttackerStartLocation());
	}
	
	public void reset(Vector3f location) {
		this.health = BaseAttacker.MAXHEALTH;
		
		setLocalTranslation(location);
		updateRenderState();
		
		baseAttackerController.reset();
		
		baseAttackerController.setActive(true);
		
		setCullHint(CullHint.Never);
		setIsCollidable(true);
		
		if(modelIndex == 0) {
			controller.setTimes(2, 20);
		}else{
			controller.setTimes(16, 26);
		}
		controller.setRepeatType(Controller.RT_CYCLE);
		controller.setActive(true);
	}

	public BaseAttackerController getBaseAttackerController() {
		return baseAttackerController;
	}
	
	

	public void hit(Person person, int damage) {
		hit(damage);
		
		if(health <= 0) {
			person.killedZombie();
			if(person != ((RotwGameState)GameStateManager.getInstance().getChild("gameState")).getPlayer()) {
				BasicSyncManager syncManager = 
					((RotwGameState)GameStateManager.getInstance().getChild("gameState")).getSyncManager();
				if(syncManager instanceof Server) {
					AttackerKilledMessage attMsg = new AttackerKilledMessage();
					((Server)syncManager).getServer().sendToPlayer(attMsg, person.getPlayerId());
				}
			}
		}
	}
	
	
	public void hit(int damage) {
		this.health -= damage;
		
		if(health <= 0) {
			died(true);
		}
	}
	
	public void died(boolean sendMsg) {
		baseAttackerController.setActive(false);
		
		if(modelIndex == 0) controller.setTimes(59, 75);
		else controller.setTimes(230, 251);
		controller.setRepeatType(Controller.RT_CLAMP);

		AttackerList.removeAttacker(this);
		AttackerList.addDeadAttacker(this);
		
		timeDied = System.currentTimeMillis();
		
		if(sendMsg) {
			AttackerDiedMessage attMsg = new AttackerDiedMessage();
			attMsg.setAttackerId(getAttackerId());
			
			BasicSyncManager syncManager = 
				((RotwGameState)GameStateManager.getInstance().getChild("gameState")).getSyncManager();
			if(syncManager instanceof Server) {
				((Server)syncManager).getServer().sendToAll(attMsg);
			}
		}
	}
	
	public boolean resetAfterDeath() {
		if( (System.currentTimeMillis() - timeDied) < 5000) return false;
		
		setUnused();
		
		RotwGameState gameState = (RotwGameState)GameStateManager.getInstance().getChild("gameState");
		DefendYourBase gameMode = (DefendYourBase)gameState.getGameMode();
		
		
		gameMode.decreaseAttackerLag(50);
		BaseAttacker.MAXHEALTH += 5;
		
		return true;
	}
	
	public void setUnused() {
		setCullHint(CullHint.Always);
		setIsCollidable(false);
		setLocalTranslation(0, -999, 0);
		
		AttackerList.addUnusedAttacker(this);
	}

	public void setAttackerId(int attackerId) {
		this.attackerId = attackerId;
	}

	public int getAttackerId() {
		return attackerId;
	}

	public int getModelIndex() {
		return modelIndex;
	}
	
	
	
	public static void attackerConquered() {
		if(Game.getGame().getSettings().isSFX()) {
			Sound.getInstance().getAudioTrack("sounds/thunder.wav").play();
		}
		
		if(AttackerList.getAttackers() != null) {
			for(BaseAttacker att:AttackerList.getAttackers()) {
				att.setUnused();
			}
		}
		AttackerList.getAttackers().clear();
		
		
		
		BaseAttacker.MAXHEALTH = 100;
		
		
		RotwGameState gameState = (RotwGameState)GameStateManager.getInstance().getChild("gameState");
		DefendYourBase gameMode = (DefendYourBase)gameState.getGameMode();
		
		
		gameMode.resetAttackerLag();
		
		gameState.addChatMessage("YOUR BASE HAS BEEN CONQUERED!");
		
		int timeSurvived = (int)((System.currentTimeMillis() - OnlineStatistics.defendStarted)/1000f);
		gameState.addChatMessage("YOU SURVIVED "+timeSurvived+" SECONDS");
		
		
		if(OnlineStatistics.updateDefendTime()) {
			gameState.addChatMessage("NEW RECORD!");
		}
	}
}
